import { useState, useRef, useCallback, useEffect, useMemo } from 'react'
import { useRouter } from 'next/router'
import Image from 'next/image'
import Head from 'next/head'
import {
  Textarea,
  Input,
  Select,
  SelectItem,
  Button,
  Tooltip,
  Modal,
  ModalContent,
  ModalBody,
} from '@nextui-org/react'
import { Inter } from 'next/font/google'
import Title from '@/components/Title'
import Steps from '@/components/Steps'
import Intro from '@/components/Intro'
import Entries from '@/components/Entries'
import FAQ from '@/components/FAQ'
import Output from '@/components/Output'

import { useGlobalContext } from '@/contexts'
import initAssistantRequest from '@/shared/assistantRequest'
import { getPageData, getCreateParams, getSelectOptions } from '@/shared/utils'
import { AssistantProps } from '~/src/services'

import iconMagic from '@/assets/icons/ic_magic.png'
import runoutPC from '@/assets/runout-pc.png'
import runoutMobile from '@/assets/runout-mobile.png'

const inter = Inter({ subsets: ['latin'] })

const Generator = () => {
  const router = useRouter()
  const { pathname } = router
  const { insData } = useGlobalContext()
  const [keywords, setKeywords] = useState('')
  const [desc, setDesc] = useState('')
  const [accountType, setAccountType] = useState('')
  const [nameStyle, setNameStyle] = useState('')

  const [modalOpen, setModalOpen] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [errorTips, setErrorTips] = useState('')
  const [errorTipsOpen, setErrorTipsOpen] = useState(false)
  const [replyData, setReplyData] = useState('')
  const [historyList, setHistoryList] = useState<
    { timestamp: number; value: string }[]
  >([])

  const abortController = useRef<AbortController>()
  const textRef = useRef('')
  const timestampRef = useRef(0)

  const pageData = useMemo(
    () => getPageData(pathname, insData) as AssistantProps,
    [pathname, insData]
  )

  const accountData = useMemo(() => {
    const code = 'Account Type'
    return getSelectOptions(pageData, code)
  }, [pageData])

  const styleData = useMemo(() => {
    const code = 'Style'
    return getSelectOptions(pageData, code)
  }, [pageData])

  useEffect(() => {
    if (!accountType && accountData?.length) {
      setAccountType(accountData[0].value)
    }
  }, [accountType, accountData?.length])

  useEffect(() => {
    if (!nameStyle && styleData?.length) {
      setNameStyle(styleData[0].value)
    }
  }, [nameStyle, styleData?.length])

  useEffect(() => {
    setTimeout(() => setErrorTipsOpen(false), 1000 * 5)
  }, [errorTips])

  const handleMessagesStream = useCallback((stream: string) => {
    if (!stream) return

    if (!textRef.current) {
      timestampRef.current = new Date().getTime()
    }

    textRef.current += stream.replace(/(\n|-=- --)/g, ' ')
    textRef.current = textRef.current.replace(/(\n|-=-n--)/g, '<br/>')

    setReplyData(textRef.current)
  }, [])

  const errorHandler = useCallback((type: string, failedType: string) => {
    // trackAssistant('error', { status: type, failedType })
    setErrorTips(failedType)
    setErrorTipsOpen(true)
  }, [])

  const handleOpenError = useCallback(
    (status: string) => {
      setIsLoading(false)

      const maps: { [key: string]: () => void } = {
        '202': () => {
          errorHandler('202', 'validate failed')
        },
        '241': () => {
          // credit run out
          // errorHandler('241', 'credit run out')
          setModalOpen(true)
        },
        '277': () => {
          errorHandler('277', 'request too much')
        },
        '278': () => {
          errorHandler('278', 'request frequency has reached the upper limit')
        },
        '279': () => errorHandler('279', 'forbidden words'),
        '280': () => {
          errorHandler(
            '280',
            'The input context exceeds 2000 characters, please cut it down and try again.'
          )
        },
        '401': () => {
          // free credit run out
          // errorHandler('401', 'free credit run out')
          setModalOpen(true)
        },
        '403': () => {
          // forbidden words
          errorHandler(
            '403',
            'There is a risk of violations, which may be due to factors such as violations and pornography'
          )
        },
        '429': () => {
          errorHandler('429', 'request frequency has reached the upper limit')
        },
      }
      if (maps[status]) {
        maps[status]()
        return
      } else {
        errorHandler(`${status}`, 'Server Error')
      }
    },
    [errorHandler]
  )

  const handleResetAnswerState = () => {
    textRef.current = ''
    timestampRef.current = 0
  }

  const handleMessageEnd = () => {
    setReplyData('')
    setHistoryList((prev) => [
      { timestamp: timestampRef.current, value: textRef.current },
      ...prev,
    ])
  }

  const handleGenerate = () => {
    if (!pageData) return
    const { assistantRequest, abortController: controller } =
      initAssistantRequest()

    abortController.current = controller

    setIsLoading(true)

    const createPrams = getCreateParams(pageData, [
      keywords,
      desc,
      accountType,
      nameStyle,
    ])
    console.log('createPrams >>>>', createPrams)

    assistantRequest({
      data: createPrams,
      language: 'en',
      onOpenSuccess(response: any) {
        console.log('onOpenSuccess event >>>', response)
        handleResetAnswerState()
        if (response.status !== 200) {
          handleOpenError(response.status)
        }
      },
      onOpenError: (response: any) => {
        console.log('onOpenError event >>>', response)
        handleOpenError(response.status)
      },
      onMessage: (event: any) => {
        handleMessagesStream(event?.data)
      },
      onMessageEnd: () => {
        console.log('onMessageEnd event >>>')
        handleMessageEnd()
        // handleMessageStreamEnd()
      },
      onClose: () => {
        console.log('onClose event >>>')
        setIsLoading(false)
      },
      onError: (event: any) => {
        console.log('onError event >>>', event)
        setIsLoading(false)
      },
    }).catch((err) => {
      console.log('assistantRequest err >>>>', err)
    })
  }

  return (
    <>
      <div className="flex flex-col gap-y-4 w-[840px] min-h-[316px] px-3.5 py-6 bg-white mx-[auto] mb-row shadow-lg max-sm:w-full max-sm:mb-0 rounded-[20px]">
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-black text-base font-bold">
              Short Description *
            </span>
            <span className="text-sm text-secondary">
              {keywords.length}/200
            </span>
          </div>
          <Textarea
            className="text-black"
            variant="bordered"
            placeholder="What is the bio about?"
            value={keywords}
            onValueChange={(val) => {
              setKeywords(val.slice(0, 200))
            }}
          />
        </div>
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-black text-base font-bold">
              Call to Action
            </span>
            <span className="text-sm text-secondary">{desc.length}/100</span>
          </div>
          <Input
            className="text-black"
            variant="bordered"
            placeholder="Your call to action"
            value={desc}
            onValueChange={(val) => {
              setDesc(val.slice(0, 100))
            }}
          />
        </div>
        <div className="flex flex-row justify-between gap-x-8 max-sm:flex-col max-sm:gap-y-4">
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-black text-base font-bold">
                Account Type
              </span>
            </div>
            {accountData && (
              <Select
                aria-label="select language"
                variant="bordered"
                selectionMode="single"
                items={accountData}
                selectedKeys={[accountType]}
                defaultSelectedKeys={[accountType]}
                onSelectionChange={(val: any) => {
                  setAccountType(val.currentKey)
                }}
              >
                {accountData.map((item) => (
                  <SelectItem
                    className="text-black"
                    key={item.value}
                    value={item.value}
                  >
                    {item.label}
                  </SelectItem>
                ))}
              </Select>
            )}
          </div>
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-black text-base font-bold">Name Style</span>
            </div>
            {styleData && (
              <Select
                aria-label="select language"
                variant="bordered"
                selectionMode="single"
                items={styleData}
                selectedKeys={[nameStyle]}
                onSelectionChange={(val: any) => {
                  setNameStyle(val.currentKey)
                }}
              >
                {styleData.map((item) => (
                  <SelectItem
                    key={item.value}
                    className="text-black"
                    value={item.value}
                  >
                    {item.label}
                  </SelectItem>
                ))}
              </Select>
            )}
          </div>
        </div>
        <Tooltip
          color={'danger'}
          isOpen={errorTipsOpen}
          showArrow
          isDismissable
          placement="bottom"
          content={errorTips}
        >
          <Button
            className="flex w-full button-primary cursor-pointer"
            isDisabled={!keywords.length || isLoading}
            isLoading={isLoading}
            onClick={handleGenerate}
          >
            <Image src={iconMagic} alt="icon" width={22} height={22} />
            Generate
          </Button>
        </Tooltip>
        <div className="flex flex-col gap-4 max-sm:hidden">
          {[
            { timestamp: timestampRef.current, value: replyData },
            ...historyList,
          ].map((item, index) => (
            <Output
              key={`${item.timestamp}-${index}`}
              timeStamp={new Date().getTime()}
              content={item.value}
              // onCopy={() => {}}
              onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
            />
          ))}
        </div>
      </div>
      <div className="flex flex-col gap-6 pt-6 lg:hidden">
        {[
          { timestamp: timestampRef.current, value: replyData },
          ...historyList,
        ].map((item, index) => (
          <Output
            key={`${item.timestamp}-${index}`}
            timeStamp={new Date().getTime()}
            content={item.value}
            // onCopy={() => {}}
            onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
          />
        ))}
      </div>
      <Modal
        isOpen={modalOpen}
        placement="center"
        onClose={() => setModalOpen(false)}
      >
        <ModalContent>
          <ModalBody className="p-0">
            <Image
              className="max-sm:hidden"
              src={runoutPC}
              alt="run out picture"
              width={819}
              height={662}
            ></Image>
            <Image
              className="sm:hidden"
              src={runoutMobile}
              alt="run out picture"
              width={640}
              height={872}
            ></Image>
          </ModalBody>
        </ModalContent>
      </Modal>
    </>
  )
}

export default function Home() {
  const StepsData = {
    title: 'Boost Your Instagram Profile with AI Bio Generator',
    desc: `Your Instagram bio is a quick snapshot that introduces who you are and what your profile is about. A well-crafted bio can significantly boost your growth on Instagram. Use our Instagram Bio Generator to create a unique and eye-catching bio in just three easy steps!`,
    steps: [
      {
        step: 'Step 1',
        title: 'Describe yourself',
        desc: 'First, provide the AI tool information about you or your brand. This can include but is not limited to, your name, hobbies, industry, and the main goal of your Instagram account – whether it’s increasing followers, driving traffic to your website or blog, promoting products, or anything else. This information helps AI generate a unique Instagram profile bio for you.',
        img: require('@/assets/bio/step-1.png').default,
      },
      {
        step: 'Step 2',
        title: 'Add more settings ',
        desc: `Select your account type and preferred bio style from the drop-down menu, for example, whether you want a professional tone or a more casual one. If the style options don't meet your needs, you can specify it in the description.`,
        img: require('@/assets/bio/step-2.png').default,
      },
      {
        step: 'Step 3',
        title: 'Generatr your Bio',
        desc: `Click the "Generate" button and you'll instantly get three personalized resumes complete with emojis. If they don't meet your expectations, you can keep generating until you find one that suits you. Then, just click the Copy button and paste the bio of your choice into your Instagram profile.`,
        img: require('@/assets/bio/step-3.png').default,
      },
    ],
  }
  const IntroData = {
    title: 'How Does AI Instagram Bio Generator Work?',
    desc: [
      `Instagram Bio Generator uses artificial intelligence to craft engaging and unique Bios in seconds. It uses advanced natural language processing algorithms that consider the context, the information you provide, and your desired tone. This allows it to generate a Bio that accurately reflects who you are and your interests, and includes relevant keywords and hashtags to boost your visibility on Instagram.`,
    ],
    intros: [
      {
        title: 'Elevate Instagram presence',
        desc: `This tool allows you to express your personality or brand concisely and attractively. Specify the style you want and it will generate content using related keywords and hashtags to boost your Instagram performance, and help attract more followers interested in your content or services.`,
        img: require('@/assets/bio/icon-reels.png'),
      },
      {
        title: 'Easy to use',
        desc: `Our Instagram Bio Generator is free and easy to use, allowing anyone to create a unique and professional Instagram bio in just a few seconds. Users simply provide some basic information about themselves or their brand, and the AI generates a bio. `,
        img: require('@/assets/bio/icon-thunmup.png'),
      },
      {
        title: 'Quick and efficient',
        desc: `If you try to craft an Instagram bio yourself, it may take hours and a lot of effort. However, using AI simplifies this process. It can quickly generate multiple Bio examples. This Bio generator tool is not only suitable for Instagram but can also be used to create profiles on other platforms.`,
        img: require('@/assets/bio/icon-fast.png'),
      },
    ],
  }
  const EntriesData = {
    title: 'More Free Tools to Grow Your IG',
    entries: [
      {
        label: 'Instagram Hashtag Generator',
        link: '/instagram-hashtag-generator/',
      },
      {
        label: 'Instagram Username Generator',
        link: '/instagram-username-generator/',
      },
      {
        label: 'Instagram Caption Generator',
        link: '/instagram-caption-generator/',
      },
    ],
  }
  const FAQData = {
    title: 'FAQs',
    faqs: [
      {
        question: 'How long can Instagram bio be?',
        answer: `An Instagram bio can be up to 150 characters long.`,
      },
      {
        question: 'Should I use emojis in bio?',
        answer:
          'Yes, you should consider using emojis in your Instagram Bio. Emojis make your profile more attractive and easier to read, and can also help communicate your brand voice or personal style effectively​.',
      },
      {
        question:
          'Is there a limit to the number of Instagram Bios I can generate?',
        answer:
          'Since our Instagram AI Bio Generator is free, we limit the number of Instagram bios you can generate daily to  avoid excessive consumption. However, rest assured that our trained AI can effectively generate satisfying Bios within a limited number of times. ',
      },
    ],
  }
  return (
    <main
      className={`w-view min-h-screen mx-[auto] ${inter.className} max-sm:w-sView max-sm:px-[10px]`}
    >
      <Head>
        <title>
          Free AI Instagram Bio Generator - Best Bio Maker with Emojis
        </title>
        <meta
          name="description"
          content="Our Instagram bio generator is free to use and helps you create a unique and eye-catching bio for Instagram effortlessly."
        />
        <meta
          property="og:title"
          content="Free AI Instagram Bio Generator - Best Bio Maker with Emojis"
        />
        <meta
          property="og:description"
          content="Our Instagram bio generator is free to use and helps you create a unique and eye-catching bio for Instagram effortlessly."
        />
      </Head>
      <Title
        title="AI Instagram Bio Generator"
        desc="AI Bio Generator can quickly create eye-catching Instagram Bios. Just describe your account and choose a style, and you'll have a unique profile in seconds."
      ></Title>
      <Generator />
      <Steps {...StepsData} />
      <Intro {...IntroData} />
      <FAQ {...FAQData} />
      <Entries {...EntriesData} />
    </main>
  )
}
